package service

import (
	"context"
	"database/sql"
	"fx_swift_boss/api"
	"fx_swift_boss/internal/model"
	"fx_swift_boss/internal/temple"
	"fx_swift_boss/pkg/code"
	"fx_swift_boss/pkg/global"
	"fx_swift_boss/pkg/internalerrors"
	"fx_swift_boss/pkg/logger"
	"fx_swift_boss/pkg/mail"
	"fx_swift_boss/pkg/page"
	"fx_swift_boss/pkg/utils"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/golang-module/carbon/v2"
	"github.com/shopspring/decimal"
	"github.com/spf13/cast"
)

type IAgentSrv interface {
	// 代理商管理列表
	AgentList(ctx context.Context, req *api.AgentListReq) (*page.Collection[*api.AgentListRes], error)
	// 代理商冻结/解冻操作
	OperatorProcess(ctx context.Context, req *api.OperatorProcessReq) error
	// 代理商详情
	GetAgentDetails(ctx context.Context, account string) (*api.GetAgentDetailsRes, error)
	// 代理商资质审核列表
	AgentApplyReview(ctx context.Context, req *api.AgentApplyReviewReq) (*page.Collection[*api.AgentApplyReviewRes], error)
	// 资质审核操作
	OperatorApplyReview(ctx context.Context, req *api.OperatorApplyReviewReq) error
	// 充值审核列表
	DiscountOrderList(ctx context.Context, req *api.DiscountOrderListReq) (*page.Collection[*api.DiscountOrderListRes], error)
	// 充值订单详情
	DiscountOrderDetails(ctx context.Context, discountOrderNo string) (*api.DiscountOrderDetailsRes, error)
	// 充值订单审核操作
	DiscountOrderOperator(ctx context.Context, req *api.DiscountOrderOperatorReq) error
	// 获取所有代理商的companyName
	GetAgentCompanyInfo(ctx context.Context) ([]*api.GetAgentCompanyInfoRes, error)
	// 代理商资金流水
	CashFlowList(ctx context.Context, req *api.CashFlowListReq) (*page.Collection[*api.CashFlowListRes], error)
	// 管理费轮训
	ManagementFee(ctx context.Context) error
	// 修改代理商发卡费
	AdaptManagementFee(ctx context.Context, account, fee string) error
	// 修改代理商充值手续费
	AdaptFee(ctx context.Context, account, fee string) error
	// 修改代理商发卡费
	AdaptCardOpeningFee(ctx context.Context, account, cardOpeningFee string) error
}
type agentSrv struct {
}

func NewAgentSrv() IAgentSrv {
	return &agentSrv{}
}

// 修改代理商发卡费
func (a *agentSrv) AdaptCardOpeningFee(ctx context.Context, account, cardOpeningFee string) error {
	var (
		err      error
		agentObj *model.FxAgent
	)

	if account == "" {
		return internalerrors.New(code.ErrUnknown, "账号不能为空")
	}
	if cardOpeningFee == "" {
		return internalerrors.New(code.ErrUnknown, "发卡费不能为空")
	}
	if utils.IsNumeric(cardOpeningFee) == false {
		return internalerrors.New(code.ErrUnknown, "必须输入数值")
	}

	if err = global.GFDB.Ctx(ctx).Schema("card").Model("fx_agent").
		Where("account=?", account).Scan(&agentObj); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	if agentObj == nil {
		return internalerrors.New(code.ErrUnknown, "暂无修改记录")
	}

	if _, err = global.GFDB.Schema("card").Model("fx_agent").
		Data(g.Map{"card_opening_fee": cardOpeningFee}).
		Where("account=?", account).Update(); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	return err
}

// 修改代理商充值手续费
func (a *agentSrv) AdaptFee(ctx context.Context, account, fee string) error {
	var (
		err      error
		agentObj *model.FxAgent
	)
	if account == "" {
		return internalerrors.New(code.ErrUnknown, "账号不能为空")
	}
	if fee == "" {
		return internalerrors.New(code.ErrUnknown, "手续费不能为空")
	}
	if utils.IsNumeric(fee) == false {
		return internalerrors.New(code.ErrUnknown, "必须输入数值")
	}
	if fee < "0" {
		return internalerrors.New(code.ErrUnknown, "手续费不能小于等于0")
	}

	if err = global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_agent").
		Where("account=?", account).Scan(&agentObj); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	if agentObj == nil {
		return internalerrors.New(code.ErrUnknown, "暂无修改记录")
	}

	if _, err = global.GFDB.Schema("card").Model("fx_agent").
		Data(g.Map{"fee": fee}).
		Where("account=?", account).Update(); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	return err
}

// 代理商管理列表
func (a *agentSrv) AgentList(ctx context.Context, req *api.AgentListReq) (*page.Collection[*api.AgentListRes], error) {
	var (
		err        error
		resultList []*api.AgentListRes
		total      int
	)
	collectionDto := &page.Collection[*api.AgentListRes]{}
	collectionDto.Page = req.Page
	collectionDto.PageSize = req.PageSize

	mod := global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_agent fa").
		LeftJoin("card.fx_enterprise_account_apply fe", "fa.account=fe.account").
		LeftJoin("card.fx_account fat", "fa.account=fat.account").
		LeftJoin("card.fx_agent_management fam", "fam.account=fat.account")
	mod.Fields("fa.account,fa.fee,fa.card_opening_fee,fam.management_fee,fe.company_name,fa.email,fa.created_at,fat.balance,fa.is_freeze,fam.status")
	mod.Where("fe.status ='pass'")
	if len(req.CompanyName) > 0 {
		mod.Where("fe.company_name=?", req.CompanyName)
	}

	if len(req.Email) > 0 {
		mod.Where("fa.email=?", req.Email)
	}

	if len(req.IsFreeze) > 0 {
		mod.Where("fa.is_freeze=?", req.IsFreeze)
	}

	if len(req.Status) > 0 {
		mod.Where("fam.status=?", req.Status)
	}

	if len(req.SortFields) > 0 && len(req.SortMethod) > 0 {
		if req.SortFields == "balance" {
			mod.Order("fat." + req.SortFields + " " + req.SortMethod)
		} else {
			mod.Order("fa." + req.SortFields + " " + req.SortMethod)
		}
	}
	mod.Limit(int(page.PageToOffset(req.Page, req.PageSize)), cast.ToInt(req.PageSize))
	err = mod.ScanAndCount(&resultList, &total, false)
	collectionDto.TotalPage = page.GetTotalPage(req.Page, req.PageSize, cast.ToInt64(total))

	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}

	collectionDto.Total = cast.ToInt64(total)
	collectionDto.List = resultList
	return collectionDto, err
}

// 代理商冻结/解冻操作
func (a *agentSrv) OperatorProcess(ctx context.Context, req *api.OperatorProcessReq) error {
	var (
		err      error
		result   sql.Result
		rowsNums int64
		agentObj *model.FxAgent
	)
	defer func() {
		if r := recover(); r != nil {
			logger.SugarLogger.Error(err)
		}
	}()
	if err = global.GFDB.Ctx(ctx).Schema("card").Model("fx_agent").Data(g.Map{"is_freeze": req.OperatorStr}).
		Where("account=?", req.Account).Scan(&agentObj); err != nil || agentObj == nil {
		return internalerrors.New(code.ErrUnknown, "帐号数据异常")
	}

	result, err = global.GFDB.Schema("card").Model("fx_agent").Data(g.Map{"is_freeze": req.OperatorStr}).
		Where("account=?", req.Account).Update()
	if err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "状态更新异常")
	}
	rowsNums, err = result.RowsAffected()
	if err != nil || rowsNums == 0 {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "状态更新异常")
	}
	if req.FreezeType == "1" {
		// 发送邮件
		go mail.SendMail(agentObj.Email, "", temple.AccountExceptionHtmlStr, global.ViperObj.GetString("email.freeze_account"))
	} else if req.FreezeType == "2" {
		// 发送邮件
		go mail.SendMail(agentObj.Email, "", temple.AccountExceptionHtmlStr, global.ViperObj.GetString("email.freeze_account"))
		// 并且冻结该代理商下面所有卡
		go FreezeAgentAllCard(ctx, req.Account, "0")
	}
	return err
}

// 代理商详情
func (a *agentSrv) GetAgentDetails(ctx context.Context, account string) (*api.GetAgentDetailsRes, error) {
	type DbVo struct {
		Email               string          `json:"email"`
		IsFreeze            int             `json:"is_freeze"`
		Status              string          `json:"status"`
		CompanyName         string          `json:"company_name"`
		CompanyTime         string          `json:"company_time"`
		Image               string          `json:"image"`
		ContactPerson       string          `json:"contact_person"`
		Phone               string          `json:"phone"`
		CompanyAddress      string          `json:"company_address"`
		RegisterCode        string          `json:"register_code"`
		CompanyType         string          `json:"company_type"`
		CountryId           int64           `json:"country_id"`
		ManagementFee       decimal.Decimal `json:"management_fee"`
		Fee                 decimal.Decimal `json:"fee"`
		CardOpeningFee      decimal.Decimal `json:"card_opening_fee"`
		FutureManagementFee decimal.Decimal `json:"future_management_fee"`
		UpdatedAt           string          `json:"updated_at"`
	}
	var (
		err            error
		dbVo           *DbVo
		result         = &api.GetAgentDetailsRes{}
		countryObj     *model.FxCountry
		companyTypeObj *model.FxCompanyType
	)
	if err = global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_agent fa").
		LeftJoin("card.fx_enterprise_account_apply fea", "fa.account = fea.account").
		LeftJoin("card.fx_agent_management fam", "fam.account = fea.account").
		Fields("fa.email,fa.fee,fa.card_opening_fee,fa.is_freeze,fea.status,fea.company_name,fea.company_time,"+
			"fea.image,fea.contact_person,fea.phone,fea.company_address,fea.register_code,fea.company_type,"+
			"fea.country_id,fam.management_fee,fam.future_management_fee,fea.updated_at").
		Where("fa.account=?", account).Scan(&dbVo); err != nil {
		logger.SugarLogger.Error(err)
		return nil, internalerrors.New(code.ErrUnknown, "查询异常")
	}

	if dbVo == nil {
		return nil, internalerrors.New(code.ErrUnknown, "帐号数据异常")
	}

	if err = global.GFDB.Schema("card").Model("fx_company_type").Where("id=?", dbVo.CompanyType).Scan(&companyTypeObj); err != nil {
		logger.SugarLogger.Error(err)
		return nil, internalerrors.New(code.ErrUnknown, "查询异常")
	}

	if err = global.GFDB.Schema("fx").Model("fx_country").Where("id=?", dbVo.CountryId).Scan(&countryObj); err != nil {
		logger.SugarLogger.Error(err)
		return nil, internalerrors.New(code.ErrUnknown, "查询异常")
	}

	if countryObj != nil {
		result.CountryName = api.NameInfo{
			ChineseName: countryObj.ChineseName,
			EnglishName: countryObj.EnglishName,
		}
	}
	result.Email = dbVo.Email
	result.IsFreeze = cast.ToString(dbVo.IsFreeze)
	result.Status = dbVo.Status
	result.CompanyName = dbVo.CompanyName
	result.CompanyTime = dbVo.CompanyTime
	result.Additional = dbVo.Image
	result.ContactPerson = dbVo.ContactPerson
	result.Phone = dbVo.Phone
	result.CompanyAddress = dbVo.CompanyAddress
	if companyTypeObj != nil {
		result.CompanyType = api.NameInfo{
			ChineseName: companyTypeObj.ChineseName,
			EnglishName: companyTypeObj.EnglishName,
		}
	}
	result.RegisterCode = dbVo.RegisterCode
	result.ManagementFee = dbVo.ManagementFee.String()
	result.FutureManagementFee = dbVo.FutureManagementFee.String()
	result.Fee = dbVo.Fee.String()
	result.CardOpeningFee = dbVo.CardOpeningFee.String()
	result.UpdatedAt = dbVo.UpdatedAt
	return result, err
}

// 代理商资质审核列表
func (a *agentSrv) AgentApplyReview(ctx context.Context, req *api.AgentApplyReviewReq) (*page.Collection[*api.AgentApplyReviewRes], error) {
	var (
		err        error
		resultList []*api.AgentApplyReviewRes
		total      int
	)

	collectionDto := &page.Collection[*api.AgentApplyReviewRes]{}
	collectionDto.Page = req.Page
	collectionDto.PageSize = req.PageSize

	mod := global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_enterprise_account_apply fea").
		LeftJoin("card.fx_agent fa", "fa.account = fea.account").
		Fields("fea.account,fea.company_name,fea.status,fea.refuse_reason,fa.email,fa.is_freeze")
	if len(req.CompanyName) > 0 {
		mod.Where("fea.company_name=?", req.CompanyName)
	}

	if len(req.Status) > 0 {
		mod.Where("fea.status=?", req.Status)
	}

	if len(req.SortFields) > 0 && len(req.SortMethod) > 0 {
		mod.Order("fea " + req.SortFields + " " + req.SortMethod)
	}
	mod.Where("fea.status !='draft'")
	mod.Limit(int(page.PageToOffset(req.Page, req.PageSize)), cast.ToInt(req.PageSize))
	err = mod.ScanAndCount(&resultList, &total, false)
	collectionDto.TotalPage = page.GetTotalPage(req.Page, req.PageSize, cast.ToInt64(total))

	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	collectionDto.Total = cast.ToInt64(total)
	collectionDto.List = resultList
	return collectionDto, err
}

// 资质审核操作
func (a *agentSrv) OperatorApplyReview(ctx context.Context, req *api.OperatorApplyReviewReq) error {
	var (
		err      error
		result   sql.Result
		rowsNums int64
		//msg      string
		//nums     int
		//sqlId    int64
		agentObj *model.FxAgent
	)
	global.GFDB.Schema("card").Model("fx_agent").Where("account=?", req.Account).Scan(&agentObj)
	db := g.DB().Schema("card")

	if req.OperatorStr == "pass" {
		// 更新状态
		err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
			result, err = tx.Model("fx_enterprise_account_apply").
				Data(g.Map{"status": req.OperatorStr, "refuse_reason": req.RefuseReason}).
				Where("account=?", req.Account).Update()
			if err != nil {
				logger.SugarLogger.Error(err)
				return internalerrors.New(code.ErrUnknown, "状态更新异常")
			}
			rowsNums, err = result.RowsAffected()
			if err != nil || rowsNums == 0 {
				logger.SugarLogger.Error(err)
				return internalerrors.New(code.ErrUnknown, "状态更新异常")
			}

			if result, err = tx.Insert("fx_agent_management", &model.FxAgentManagement{
				Account:       req.Account,
				Status:        "noopen",
				ManagementFee: cast.ToString(global.ViperObj.GetFloat64("management_fee")),
			}); err != nil {
				logger.SugarLogger.Error(err)
				return internalerrors.New(code.ErrUnknown, "注册失败")
			}
			rowsNums, err = result.RowsAffected()
			if rowsNums == 0 {
				return internalerrors.New(code.ErrUnknown, "注册失败")
			}
			return nil
		})
		if err == nil {
			// 发送站内通知
			//msg = fmt.Sprint("恭喜您注册成功！请于3日之内充值第一笔资金，我们将为您开通帐户管理计划。")
			//err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
			//	nums, err = tx.Model("card.fx_notify").Where("account=? and content=?", req.Account, msg).Count()
			//	if err != nil {
			//		return err
			//	}
			//	if nums == 0 {
			//		sqlId, err = tx.Model("fx_notify").InsertAndGetId(&model.FxNotify{
			//			Account: req.Account,
			//			Content: msg,
			//			Status:  0,
			//		})
			//	}
			//	return nil
			//})
			//wRes := &api.WedStockRes{
			//	Account: req.Account,
			//	Id:      cast.ToString(sqlId),
			//	Content: msg,
			//}
			//notify.SendMsgToWebStock(wRes)
			// 发送邮件
			go mail.SendMail(agentObj.Email, "", temple.SuccessHtml, global.ViperObj.GetString("email.register"))
		}
	} else if req.OperatorStr == "refuse" {
		result, err = global.GFDB.Schema("card").Ctx(ctx).Model("fx_enterprise_account_apply").
			Data(g.Map{"status": req.OperatorStr, "refuse_reason": req.RefuseReason}).
			Where("account=?", req.Account).Update()
		if err != nil {
			logger.SugarLogger.Error(err)
			return internalerrors.New(code.ErrUnknown, "状态更新异常")
		}

		// 发送邮件
		go mail.SendMail(agentObj.Email, "", temple.FailHtml, global.ViperObj.GetString("email.register"))
	}
	return err
}

// 充值审核列表
func (a *agentSrv) DiscountOrderList(ctx context.Context, req *api.DiscountOrderListReq) (*page.Collection[*api.DiscountOrderListRes], error) {
	var (
		err        error
		resultList []*api.DiscountOrderListRes
		total      int
	)
	collectionDto := &page.Collection[*api.DiscountOrderListRes]{}
	collectionDto.Page = req.Page
	collectionDto.PageSize = req.PageSize

	mod := global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_discount_order")

	if len(req.CompanyName) > 0 {
		mod.Where("company_name=?", req.CompanyName)
	}

	if len(req.Status) > 0 {
		mod.Where("status=?", req.Status)
	}

	if len(req.SortFields) > 0 && len(req.SortMethod) > 0 {
		mod.Order(req.SortFields + " " + req.SortMethod)
	}
	mod.Order("created_at desc")
	mod.Limit(int(page.PageToOffset(req.Page, req.PageSize)), cast.ToInt(req.PageSize))
	err = mod.ScanAndCount(&resultList, &total, false)
	collectionDto.TotalPage = page.GetTotalPage(req.Page, req.PageSize, cast.ToInt64(total))

	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}

	collectionDto.Total = cast.ToInt64(total)
	collectionDto.List = resultList
	return collectionDto, err
}

// 充值订单详情
func (a *agentSrv) DiscountOrderDetails(ctx context.Context, discountOrderNo string) (*api.DiscountOrderDetailsRes, error) {
	var (
		err              error
		discountOrderObj *model.FxDiscountOrder
	)
	if err = global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_discount_order").Where("discount_order_no=?", discountOrderNo).
		Scan(&discountOrderObj); err != nil {
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}

	return &api.DiscountOrderDetailsRes{
		Amount:        discountOrderObj.Amount.String(),
		ActualAmount:  discountOrderObj.ActualAmount.String(),
		TransferImage: discountOrderObj.TransferImage,
		Status:        discountOrderObj.Status,
	}, err
}

// 充值订单审核操作
func (a *agentSrv) DiscountOrderOperator(ctx context.Context, req *api.DiscountOrderOperatorReq) error {
	type DbVo struct {
		Account       string  `json:"account"`
		Balance       float64 `json:"balance"`
		ManagementFee float64 `json:"management_fee"`
		CreatedAt     string  `json:"created_at"`
		EffectiveDate string  `json:"effective_date"`
		Status        string  `json:"status"`
	}
	var (
		err              error
		discountOrderObj *model.FxDiscountOrder
		bossAccount      string
		//dbEffectiveDate  string
		agentObj      *model.FxAgent
		accountObj    *model.FxAccount
		balance       float64
		managementFee float64
		//managementObj    *model.FxAgentManagement
		managementObj *DbVo
		redisResult   *gvar.Var
	)
	bossAccount = ctx.Value("Account").(string)

	if err = global.GFDB.Schema("card").Model("card.fx_discount_order").
		Where("discount_order_no=?", req.DiscountOrderNo).Scan(&discountOrderObj); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "查询数据异常")
	}

	if err = global.GFDB.Schema("card").Model("card.fx_agent").
		Where("account=?", discountOrderObj.Account).Scan(&agentObj); err != nil || agentObj == nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "查询数据异常")
	}

	if req.OperatorStr == "refuse" {
		_, err = global.GFDB.Schema("card").Model("fx_discount_order").
			Data(g.Map{"status": req.OperatorStr, "refuse_reason": req.RefuseReason}).
			Where("discount_order_no=?", req.DiscountOrderNo).Update()
		if err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		// 发送邮件
		go mail.SendMail(agentObj.Email, "", temple.RechargeFailHtmlStr, global.ViperObj.GetString("email.recharge_fail"))
	} else {
		db := g.DB().Schema("card")
		return db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
			_, err = tx.Model("fx_discount_order").
				Data(g.Map{"status": req.OperatorStr, "actual_amount": req.ActualAmount}).
				Where("discount_order_no=?", req.DiscountOrderNo).Update()
			if err != nil {
				return internalerrors.New(code.ErrUnknown, err.Error())
			}
			actualAmount, _ := decimal.NewFromString(req.ActualAmount)
			discountOrderObj.ActualAmount = actualAmount

			err = UpdateAccountBalanceTx(discountOrderObj, bossAccount, discountOrderObj.RechargeType, tx)

			if err == nil {
				if err = tx.Model("card.fx_account").Where("account=?", discountOrderObj.Account).Scan(&accountObj); err != nil {
					logger.SugarLogger.Error(err)
					return internalerrors.New(code.ErrUnknown, "帐户数据异常")
				}
				if err = tx.Model("card.fx_agent_management").Where("account=?", discountOrderObj.Account).Scan(&managementObj); err != nil {
					logger.SugarLogger.Error(err)
					return internalerrors.New(code.ErrUnknown, "帐户数据异常")
				}
				balance = accountObj.Balance.InexactFloat64()
				//managementFee, _ = managementObj.ManagementFee.Float64()
				managementFee = managementObj.ManagementFee

				redisResult, err = g.Redis().Get(nil, accountObj.Account+"_managementFee")
				if err != nil {
					return internalerrors.New(code.ErrUnknown, err.Error())
				}
				if redisResult.Val() != nil {
					managementFee = redisResult.Float64()
				}

				dBCreatedAt := carbon.Parse(managementObj.CreatedAt).ToDateString()
				if carbon.Parse(carbon.Now().ToDateString()).Gt(carbon.Parse(dBCreatedAt).AddDays(3)) {
					if balance >= managementFee && managementFee > 0 {
						err = operatorBalanceGteManagementFeeTX(discountOrderObj.Account, balance, managementFee, tx)
					} else if balance < managementFee && balance > 0 && managementFee > 0 {
						err = operatorBalanceLtManagementFeeTX(discountOrderObj.Account, balance, managementFee, tx)
					} else if balance < managementFee && balance == 0 && managementFee > 0 {
						err = operatorBalanceEqZeroManagementFeeTX(ctx, discountOrderObj.Account, tx)
					}
				}
			}
			return err
		})
	}
	return err
}

// 获取所有代理商的companyName
func (a *agentSrv) GetAgentCompanyInfo(ctx context.Context) ([]*api.GetAgentCompanyInfoRes, error) {
	var (
		err    error
		list   []*model.FxEnterpriseAccountApply
		result = make([]*api.GetAgentCompanyInfoRes, 0)
	)
	if err = global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_enterprise_account_apply").
		Where("status='pass'").Scan(&list); err != nil {
		return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	for _, value := range list {
		result = append(result, &api.GetAgentCompanyInfoRes{
			Id:          cast.ToString(value.ID),
			CompanyName: value.CompanyName,
		})
	}
	return result, err
}

// 代理商资金流水
func (a *agentSrv) CashFlowList(ctx context.Context, req *api.CashFlowListReq) (*page.Collection[*api.CashFlowListRes], error) {
	var (
		err        error
		resultList []*api.CashFlowListRes
		total      int
		account    string
	)
	account = ctx.Value("Account").(string)
	if len(account) == 0 {
		panic(internalerrors.New(code.ErrBind, "该帐号存在异常"))
	}
	collectionDto := &page.Collection[*api.CashFlowListRes]{}
	collectionDto.Page = req.Page
	collectionDto.PageSize = req.PageSize

	mod := global.GFDB.Ctx(ctx).Schema("card").Model("card.fx_record fr").
		LeftJoin("card.fx_enterprise_account_apply fea", "fr.account = fea.account")
	mod.Fields("fr.discount_order_no,fr.created_at,fr.amount,fr.actual_amount," +
		"fr.record_type,fr.desc as record_desc,fr.currency,fea.company_name,fr.remaining_balance")
	if len(req.DiscountOrderNo) > 0 {
		mod.WhereLike("fr.discount_order_no", "%"+req.DiscountOrderNo+"%")
	}
	if len(req.RecordType) > 0 {
		mod.Where("fr.record_type=?", req.RecordType)
	}
	if len(req.CompanyName) > 0 {
		mod.WhereLike("fea.company_name", "%"+req.CompanyName+"%")
	}
	if len(req.StartTime) > 0 && len(req.EndTime) > 0 {
		mod.Where("fr.created_at >=? and fr.created_at < ?", req.StartTime+" 00:00:00", req.EndTime+" 23:59:59")
	}
	if len(req.SortFields) > 0 && len(req.SortMethod) > 0 {
		mod.Order("fr." + req.SortFields + " " + req.SortMethod)
	}
	mod.Where("fr.account_type !='boss'")
	mod.Where("fr.account !='admin'")
	mod.Order("fr.created_at desc")
	mod.Limit(int(page.PageToOffset(req.Page, req.PageSize)), cast.ToInt(req.PageSize))
	err = mod.ScanAndCount(&resultList, &total, false)
	collectionDto.TotalPage = page.GetTotalPage(req.Page, req.PageSize, cast.ToInt64(total))

	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}

	collectionDto.Total = cast.ToInt64(total)
	collectionDto.List = resultList

	return collectionDto, err
}

// 调整代理商管理费
func (a *agentSrv) AdaptManagementFee(ctx context.Context, account, fee string) error {
	type DbVo struct {
		Account       string  `json:"account"`
		Balance       float64 `json:"balance"`
		ManagementFee float64 `json:"management_fee"`
		CreatedAt     string  `json:"created_at"`
		EffectiveDate string  `json:"effective_date"`
		Status        string  `json:"status"`
	}
	var (
		err           error
		managementObj *DbVo
		balance       float64
		managementFee float64
		accountObj    *model.FxAccount
		redisResult   *gvar.Var
		orm           = global.GFDB
	)
	if err = orm.Ctx(ctx).Schema("card").Model("card.fx_agent_management").
		Where("account=?", account).Scan(&managementObj); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	if managementObj != nil {
		if len(managementObj.EffectiveDate) == 0 && managementObj.Status == "noopen" {
			db := g.DB().Schema("card")
			return db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
				if _, err = tx.Model("fx_agent_management").
					Data(g.Map{"management_fee": fee}).
					Where("account=?", account).Update(); err != nil {
					return internalerrors.New(code.ErrUnknown, err.Error())
				}
				if err = tx.Model("card.fx_account").Where("account=?", account).Scan(&accountObj); err != nil {
					return internalerrors.New(code.ErrUnknown, err.Error())
				}
				if err = tx.Model("card.fx_agent_management").Where("account=?", account).Scan(&managementObj); err != nil {
					return internalerrors.New(code.ErrUnknown, err.Error())
				}
				balance = accountObj.Balance.InexactFloat64()
				managementFee = cast.ToFloat64(managementObj.ManagementFee)

				redisResult, err = g.Redis().Get(nil, accountObj.Account+"_managementFee")
				if err != nil {
					return internalerrors.New(code.ErrUnknown, err.Error())
				}
				if redisResult.Val() != nil {
					managementFee = redisResult.Float64()
				}

				dBCreatedAt := carbon.Parse(managementObj.CreatedAt).ToDateString()
				if carbon.Parse(carbon.Now().ToDateString()).Gt(carbon.Parse(dBCreatedAt).AddDays(3)) {
					if balance >= managementFee && managementFee > 0 {
						err = operatorBalanceGteManagementFee(account, balance, managementFee, ctx)
					} else if balance < managementFee && balance > 0 && managementFee > 0 {
						err = operatorBalanceLtManagementFee(account, balance, managementFee, ctx)
					} else if balance < managementFee && balance == 0 && managementFee > 0 {
						err = operatorBalanceEqZeroManagementFee(ctx, account)
					}
				}
				return nil
			})
		} else {
			if managementObj.Status != "outstanding" {
				if carbon.Parse(carbon.Now().ToDateString()).Gt(carbon.Parse(managementObj.EffectiveDate).AddMonthNoOverflow()) { // 说明当前的生效时间已经过期，则立即生效
					if _, err = orm.Schema("card").Model("fx_agent_management").
						Data(g.Map{"effective_date": carbon.Now().ToDateString(), "management_fee": fee, "status": "enabled"}).
						Where("account=?", account).Update(); err != nil {
						logger.SugarLogger.Error(err)
						return internalerrors.New(code.ErrUnknown, "更新有效期报错")
					}
				} else {
					lastMonth := carbon.Parse(managementObj.EffectiveDate).AddMonthNoOverflow().ToDateString()
					if _, err = orm.Schema("card").Model("fx_agent_management").
						Data(g.Map{"future_effective_date": lastMonth, "future_management_fee": fee}).
						Where("account=?", account).Update(); err != nil {
						logger.SugarLogger.Error(err)
						return internalerrors.New(code.ErrUnknown, "更新有效期报错")
					}
				}
			} else {
				logger.SugarLogger.Infof("当前用户：%s 的管理还未交清", account)
				return internalerrors.New(code.ErrUnknown, "该代理商还有未交清的管理费，请先交清。")
			}
		}
	} else {
		return internalerrors.New(code.ErrUnknown, "该代理商还未完成资质认证")
	}
	return err
}

// 管理费轮训
func (a *agentSrv) ManagementFee(ctx context.Context) error {
	logger.SugarLogger.Info("管理费轮训开始执行...................")
	type DbVo struct {
		Account       string  `json:"account"`
		Balance       float64 `json:"balance"`
		ManagementFee float64 `json:"management_fee"`
		CreatedAt     string  `json:"created_at"`
		EffectiveDate string  `json:"effective_date"`
		Status        string  `json:"status"`
	}
	var (
		err                    error
		agentManagementObjList []*DbVo
		redisResult            *gvar.Var
		managementFee          float64
		dBCreatedAt            string
		dbEffectiveDate        string
	)
	if err = global.GFDB.Schema("card").Model("card.fx_agent_management fam").
		LeftJoin("card.fx_account fa", "fam.account = fa.account").
		Fields("fam.management_fee,fam.account,fa.balance,fam.created_at,fam.effective_date,fam.status").
		Where("fam.account='138e14cd571f7c1222b0da4a323bf76f'").
		Scan(&agentManagementObjList); err != nil {
		return internalerrors.New(code.ErrUnknown, "数据查询失败")
	}
	for _, valueObj := range agentManagementObjList {

		redisResult, err = g.Redis().Get(nil, valueObj.Account+"_managementFee")
		if err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		if redisResult.Val() != nil {
			managementFee = redisResult.Float64()
		} else {
			managementFee = valueObj.ManagementFee
		}
		if len(valueObj.EffectiveDate) == 0 && valueObj.Status == "noopen" {
			dBCreatedAt = carbon.Parse(valueObj.CreatedAt).ToDateString()
			if carbon.Parse(carbon.Now().ToDateString()).Gt(carbon.Parse(dBCreatedAt).AddDays(3)) {
				if valueObj.Balance >= managementFee && managementFee > 0 {
					err = operatorBalanceGteManagementFee(valueObj.Account, valueObj.Balance, managementFee, ctx)
				} else if valueObj.Balance < managementFee && valueObj.Balance > 0 && managementFee > 0 {
					err = operatorBalanceLtManagementFee(valueObj.Account, valueObj.Balance, managementFee, ctx)
				} else if valueObj.Balance < managementFee && valueObj.Balance == 0 && managementFee > 0 {
					err = operatorBalanceEqZeroManagementFee(ctx, valueObj.Account)
				}
			}
		} else {
			dbEffectiveDate = carbon.Parse(valueObj.EffectiveDate).AddMonthNoOverflow().ToDateString()
			if carbon.Parse(carbon.Now().ToDateString()).Gt(carbon.Parse(dbEffectiveDate)) || valueObj.Status == "outstanding" {
				if valueObj.Balance >= managementFee && managementFee > 0 {
					err = operatorBalanceGteManagementFee(valueObj.Account, valueObj.Balance, managementFee, ctx)
				} else if valueObj.Balance < managementFee && valueObj.Balance > 0 && managementFee > 0 {
					err = operatorBalanceLtManagementFee(valueObj.Account, valueObj.Balance, managementFee, ctx)
				} else if valueObj.Balance < managementFee && valueObj.Balance == 0 && managementFee > 0 {
					err = operatorBalanceEqZeroManagementFee(ctx, valueObj.Account)
				}
			}
		}

	}
	return err
}

// 余额>=管理费
func operatorBalanceGteManagementFeeTX(account string, balance, managementFee float64, tx gdb.TX) error {
	var (
		err error
		//msg   string
		//nums  int
		//sqlId int64
	)
	if err = BalanceRecord(account, "admin", "帐户管理费", decimal.NewFromFloat(managementFee), tx); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "资金流水异常")
	}
	if _, err = tx.Model("fx_agent_management").
		Data("effective_date", carbon.Now().ToDateString()).
		Where("account=?", account).Update(); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, "更新管理费生效日期异常")
	}
	if err == nil {
		//msg = fmt.Sprintf("已成功扣除本月帐户管理费%sUSD/月,生效日期:%s,感谢您对FX SWIFT的支持",
		//	cast.ToString(managementFee), carbon.Now().ToDateString())
		//nums, err = tx.Model("card.fx_notify").Where("account=? and content=?", account, msg).Count()
		//if err != nil {
		//	return err
		//}
		//if _, err = tx.Model("fx_agent_management").
		//	Data(g.Map{"status": "enabled"}).
		//	Where("account=?", account).Update(); err != nil {
		//	return err
		//}
		//if nums == 0 {
		//	sqlId, err = tx.Model("fx_notify").InsertAndGetId(&model.FxNotify{
		//		Account: account,
		//		Content: msg,
		//		Status:  0,
		//	})
		//}
		//wRes := &api.WedStockRes{
		//	Account: account,
		//	Id:      cast.ToString(sqlId),
		//	Content: msg,
		//}
		//notify.SendMsgToWebStock(wRes)
		// 将该账户redis中的managementFree删除
		if _, err = g.Redis().Del(nil, account+"_managementFee"); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
	}
	return err
}

// 余额<管理费
func operatorBalanceLtManagementFeeTX(account string, balance, managementFee float64, tx gdb.TX) error {
	var (
		err error
		//msg   string
		//nums  int
		//sqlId int64
	)
	result := managementFee - balance
	if _, err = g.Redis().Set(nil, account+"_managementFee", result); err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	if err = BalanceRecord(account, "admin", "帐户管理费", decimal.NewFromFloat(balance), tx); err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	if err == nil {
		//msg = fmt.Sprintf("已成功扣除本月帐户管理费%sUSD/月，剩余应扣除%sUSD/月，请尽快充值，以免影响使用!",
		//	cast.ToString(balance), cast.ToString(result))
		//nums, err = tx.Model("card.fx_notify").Where("account=? and content=?", account, msg).Count()
		//if err != nil {
		//	return err
		//}
		//if _, err = tx.Model("fx_agent_management").
		//	Data(g.Map{"status": "outstanding"}).
		//	Where("account=?", account).Update(); err != nil {
		//	return err
		//}
		//if nums == 0 {
		//	sqlId, err = tx.Model("fx_notify").InsertAndGetId(&model.FxNotify{
		//		Account: account,
		//		Content: msg,
		//		Status:  0,
		//	})
		//}
		//wRes := &api.WedStockRes{
		//	Account: account,
		//	Id:      cast.ToString(sqlId),
		//	Content: msg,
		//}
		//notify.SendMsgToWebStock(wRes)
	}
	return err
}

// 余额<管理费 && 余额 == 0
func operatorBalanceEqZeroManagementFeeTX(ctx context.Context, account string, tx gdb.TX) error {
	var (
		err error
		//sqlId int64
		//nums  int
	)
	//msg := fmt.Sprintf("请尽快充值，我们将通过帐户余额扣除您本月的帐户管理计划费用")
	//
	//nums, err = tx.Ctx(ctx).Model("card.fx_notify").Where("account=? and content=?", account, msg).Count()
	//if err != nil {
	//	return err
	//}
	//
	//if _, err = tx.Model("fx_agent_management").
	//	Data(g.Map{"status": "outstanding"}).
	//	Where("account=?", account).Update(); err != nil {
	//	return err
	//}
	//
	//if nums == 0 {
	//	sqlId, err = tx.Model("fx_notify").InsertAndGetId(&model.FxNotify{
	//		Account: account,
	//		Content: msg,
	//		Status:  0,
	//	})
	//}
	//wRes := &api.WedStockRes{
	//	Account: account,
	//	Id:      cast.ToString(sqlId),
	//	Content: msg,
	//}
	//notify.SendMsgToWebStock(wRes)
	return err
}

// 余额>=管理费
func operatorBalanceGteManagementFee(account string, balance, managementFee float64, ctx context.Context) error {
	var (
		err error
		//msg   string
		//nums  int
		//sqlId int64
	)
	db := g.DB().Schema("card")
	err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		if err = BalanceRecord(account, "admin", "帐户管理费", decimal.NewFromFloat(managementFee), tx); err != nil {
			logger.SugarLogger.Error(err)
			return internalerrors.New(code.ErrUnknown, "资金流水异常")
		}
		if _, err = tx.Model("fx_agent_management").
			Data("effective_date", carbon.Now().ToDateString()).
			Where("account=?", account).Update(); err != nil {
			logger.SugarLogger.Error(err)
			return internalerrors.New(code.ErrUnknown, "更新管理费生效日期异常")
		}
		return nil
	})
	if err == nil {
		//msg = fmt.Sprintf("已成功扣除本月帐户管理费%sUSD/月,生效日期:%s,感谢您对FX SWIFT的支持",
		//	cast.ToString(managementFee), carbon.Now().ToDateString())
		//err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		//	nums, err = tx.Model("card.fx_notify").Where("account=? and content=?", account, msg).Count()
		//	if err != nil {
		//		return err
		//	}
		//	if _, err = tx.Model("fx_agent_management").
		//		Data(g.Map{"status": "enabled"}).
		//		Where("account=?", account).Update(); err != nil {
		//		return err
		//	}
		//	if nums == 0 {
		//		sqlId, err = tx.Model("fx_notify").InsertAndGetId(&model.FxNotify{
		//			Account: account,
		//			Content: msg,
		//			Status:  0,
		//		})
		//	}
		//	return nil
		//})
		//wRes := &api.WedStockRes{
		//	Account: account,
		//	Id:      cast.ToString(sqlId),
		//	Content: msg,
		//}
		//notify.SendMsgToWebStock(wRes)
		// 将该账户redis中的managementFree删除
		if _, err = g.Redis().Del(ctx, account+"_managementFee"); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
	}
	return err
}

// 余额<管理费
func operatorBalanceLtManagementFee(account string, balance, managementFee float64, ctx context.Context) error {
	var (
		err error
		//msg   string
		//nums  int
		//sqlId int64
	)
	result := managementFee - balance
	db := g.DB().Schema("card")
	if _, err = g.Redis().Set(ctx, account+"_managementFee", result); err != nil {
		return err
	}
	err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		if err = BalanceRecord(account, "admin", "帐户管理费", decimal.NewFromFloat(balance), tx); err != nil {
			return internalerrors.New(code.ErrUnknown, err.Error())
		}
		return nil
	})
	if err == nil {
		//msg = fmt.Sprintf("已成功扣除本月帐户管理费%sUSD/月，剩余应扣除%sUSD/月，请尽快充值，以免影响使用!",
		//	cast.ToString(balance), cast.ToString(result))
		//err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		//	nums, err = tx.Model("card.fx_notify").Where("account=? and content=?", account, msg).Count()
		//	if err != nil {
		//		return err
		//	}
		//	if _, err = tx.Model("fx_agent_management").
		//		Data(g.Map{"status": "outstanding"}).
		//		Where("account=?", account).Update(); err != nil {
		//		return err
		//	}
		//	if nums == 0 {
		//		sqlId, err = tx.Model("fx_notify").InsertAndGetId(&model.FxNotify{
		//			Account: account,
		//			Content: msg,
		//			Status:  0,
		//		})
		//	}
		//	return nil
		//})
		//wRes := &api.WedStockRes{
		//	Account: account,
		//	Id:      cast.ToString(sqlId),
		//	Content: msg,
		//}
		//notify.SendMsgToWebStock(wRes)
	}
	return err
}

// 余额<管理费 && 余额 == 0
func operatorBalanceEqZeroManagementFee(ctx context.Context, account string) error {
	var (
		err error
		//sqlId int64
		//nums  int
	)
	//msg := fmt.Sprintf("请尽快充值，我们将通过帐户余额扣除您本月的帐户管理计划费用")
	//db := g.DB().Schema("card")
	//
	//err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
	//	nums, err = tx.Model("card.fx_notify").Where("account=? and content=?", account, msg).Count()
	//	if err != nil {
	//		return err
	//	}
	//
	//	if _, err = tx.Model("fx_agent_management").
	//		Data(g.Map{"status": "outstanding"}).
	//		Where("account=?", account).Update(); err != nil {
	//		return err
	//	}
	//
	//	if nums == 0 {
	//		sqlId, err = tx.Model("fx_notify").InsertAndGetId(&model.FxNotify{
	//			Account: account,
	//			Content: msg,
	//			Status:  0,
	//		})
	//	}
	//	return nil
	//})
	//wRes := &api.WedStockRes{
	//	Account: account,
	//	Id:      cast.ToString(sqlId),
	//	Content: msg,
	//}
	//notify.SendMsgToWebStock(wRes)
	return err
}

func FreezeAgentAllCard(ctx context.Context, account, state string) error {
	var (
		err          error
		cardInfoList []*model.FxCardInfo
	)
	if err = global.GFDB.Schema("card").Model("card.fx_card_info").
		Where("account=?", account).Scan(&cardInfoList); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	if len(cardInfoList) > 0 {
		for _, cardObj := range cardInfoList {
			err = EditCardStatus(ctx, &api.EditCardStatusReq{
				CardId:    cardObj.CardId,
				Status:    state,
				UserReqNo: utils.GetHashCode(utils.GenerateCode32()),
			})
			if err != nil {
				return internalerrors.New(code.ErrUnknown, err.Error())
			}
			db := g.DB().Schema("card")
			err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
				_, err = tx.Model("fx_freeze_record").Insert(&model.FxFreezeRecord{
					CardId:       cardObj.CardId,
					Account:      account,
					OperatorType: "agent",
					Operator:     state,
				})
				if err != nil {
					logger.SugarLogger.Error(err)
					return internalerrors.New(code.ErrUnknown, "冻结操作记录异常")
				}
				return nil
			})
		}
	}
	return err
}
